#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <errno.h>
#include <stdarg.h>  
#include <ctype.h> 
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

#if defined(LINUX)
#include <unistd.h>  
#include <sys/time.h>
#include <pthread.h>
#include <dirent.h>  
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/reboot.h>
#include <linux/rtnetlink.h>
#include <sys/wait.h>  
#else
#include <io.h>
#include <direct.h>
#include <Iphlpapi.h>
#pragma comment(lib,"iphlpapi.lib") 
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#define snprintf _snprintf
#endif


#include "Logging.h"

#if !defined(LINUX)
HWND           hMainWnd;                  // 程序窗体的句柄
#endif

#if !defined(LINUX)
CListBox       *pList = NULL;
#endif

#if !defined(LINUX)
static   WSADATA      wsaData; 
#endif

static   int              gLoglevel = 0;
static   int              gLogMode = 0;
static   char             gLogDir[1024];
static   char             gAppPath[1024];
static   char             gAppName[1024];
static   char             gLocalIp[20];
static   char             gLocalMac[20];
static   char             gVersion[128];
static   int              gBigEndian = 0;

short            gNetNum;
char             gNetName[20][250];
char             gNetIp[20][20];
char             gNetMac[20][20];

//#if defined(LINUX)
//static   pthread_mutex_t  hLogMutex;
//#else
//static   HANDLE           hLogMutex;
//#endif


static   long             status_del;
static   char             gAppConfigFile[1024];
static   int              gLogInit = 0;

static   int              IsDelete = 0;
static   long             delTime = 0;


static   int              gLogSrvOk = 0;
static   short            gLogIpNum = 0;
static   unsigned short   gLogPort = 0;
//static   int              gLogFD = 0;

static   void             GetAppInfo();
static   void             DeleteExpiredFile(char *path,long expsec);
static   void             *ThreadDeleteFile(void *param);

//static   void             WebSocketLog(int sockfd,char *ip,int port);

int InitLogging(int isExit,void (*func)(char *file))
{
	char czTemp[1024];

#if !defined(LINUX)
	WSAStartup( MAKEWORD(2,0), &wsaData );
#endif

	GetAppInfo();
	gLogInit = 1;

#if defined(LINUX)
	sprintf(gAppConfigFile,"%s/%s.ini",gAppPath,gAppName);
	sprintf(gLogDir,"%s/logs",gAppPath);
#else
	sprintf(gAppConfigFile,"%s\\%s.ini",gAppPath,gAppName);
	sprintf(gLogDir,"%s\\logs",gAppPath);
#endif


	gLoglevel = 5;
	gLogMode = 3;
	gLogIpNum = 0;
	gLogPort = 12301;
	IsDelete = 1;
	delTime = 7 * 24 * 3600;

	WriteFileLog(LHINT,"");
	WriteFileLog(LHINT,"The Logging is initialized .");
	WriteFileLog(LHINT,"");

	if( !isPathExists(gAppConfigFile) )
	{
		WriteFileLog(LFATAL,"Config file(%s) does not exist",gAppConfigFile);
		WriteFileLog(LHINT,"");
		if( isExit )
		{
#if defined(LINUX)
			WriteFileLog(LFATAL,"Config file(%s) does not exist, the program terminates.",gAppConfigFile);
#else
			sprintf(czTemp,"Config file(%s) does not exist, the program terminates.",gAppConfigFile);
			WriteFileLog(LFATAL,czTemp);
			MessageBox(NULL,czTemp,"警告", MB_ICONEXCLAMATION );
#endif
			exit(-1);
		}
		WriteFileLog(LWARN,"LOG item is not set, set to the default '%s'",gLogDir);
		if( !isPathExists(gLogDir) )
		{
			WriteFileLog(LWARN,"Log directory(%s) does not exists, directory is automatically created.",gLogDir);
			PreCreatePath(gLogDir);
		}
		WriteFileLog(LWARN,"LOGLEVEL item is not set, set to the default %d",gLoglevel);
		WriteFileLog(LWARN,"LOGMODE item is not set, set to the default %d",gLogMode);
		WriteFileLog(LWARN,"LOGIPNUM item is not set, set to the default %d",gLogIpNum);
		WriteFileLog(LWARN,"LOGPORT item is not set, set to the default %d",gLogPort);
		WriteFileLog(LWARN,"ISDEL item is not set, set to the default %d",IsDelete);
	}
	else
	{
		WriteFileLog(LFATAL,"Config file(%s) exists",gAppConfigFile);
		WriteFileLog(LHINT,"");
		if( ReadCfgItem(gAppConfigFile,"LOG",gLogDir) != 0 )
		{
			WriteFileLog(LWARN,"LOG item is not set, set to the default '%s'",gLogDir);
		}
		else
		{
			WriteFileLog(LHINT,"LOG item is '%s'",gLogDir);
		}
		if( !isPathExists(gLogDir) )
		{
			WriteFileLog(LWARN,"Log directory(%s) does not exists, directory is automatically created.",gLogDir);
			PreCreatePath(gLogDir);
		}

		if( ReadCfgItem(gAppConfigFile,"LOGLEVEL",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"LOGLEVEL item is not set, set to the default %d",gLoglevel);
		}
		else
		{
			gLoglevel = atoi(czTemp);
			WriteFileLog(LHINT,"LOGLEVEL item is %d",gLoglevel);
		}

		if( ReadCfgItem(gAppConfigFile,"LOGMODE",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"LOGMODE item is not set, set to the default %d",gLogMode);
		}
		else
		{
			gLogMode = atoi(czTemp);
			WriteFileLog(LHINT,"LOGMODE item is %d",gLogMode);
		}

		if( ReadCfgItem(gAppConfigFile,"LOGIPNUM",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"LOGIPNUM item is not set, set to the default %d",gLogIpNum);
		}
		else
		{
			gLogIpNum = atoi(czTemp);
			WriteFileLog(LHINT,"LOGIPNUM item is %d",gLogIpNum);
		}

		if( ReadCfgItem(gAppConfigFile,"LOGPORT",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"LOGPORT item is not set, set to the default %d",gLogPort);
		}
		else
		{
			gLogPort = atoi(czTemp);
			WriteFileLog(LHINT,"LOGPORT item is %u",gLogPort);
		}

		if( ReadCfgItem(gAppConfigFile,"ISDEL",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"ISDEL item is not set, set to the default %d",IsDelete);
		}
		else
		{
			IsDelete = atoi(czTemp);
			WriteFileLog(LHINT,"ISDEL item is %d",IsDelete);
		}
	}

	if( IsDelete )
	{
		if( ReadCfgItem(gAppConfigFile,"DELTIME",czTemp) != 0 )
		{
			WriteFileLog(LWARN,"DELTIME item is not set, set to the default %ld",delTime);
		}
		else
		{
			delTime = atoi(czTemp) * 24 * 3600;
			WriteFileLog(LHINT,"DELTIME item is %ld",delTime);
		}
	}

	if( func != NULL )
	{
		func(gAppConfigFile);
	}

	WriteFileLog(LHINT,"");

	gBigEndian = CheckBigEndian(); 
	if( GetBigEndian() )
	{
		WriteFileLog(LWARN,"This machine is big endian CPU.");
	}
	else
	{
		WriteFileLog(LHINT,"This machine is little endian CPU.");
	}

	WriteFileLog(LHINT,"");

	WaitNetworkUp();

	WriteFileLog(LHINT,"");

	strcpy(gLocalIp,gNetIp[gLogIpNum]);
	strcpy(gLocalMac,gNetMac[gLogIpNum]);

//#if defined(LINUX)
//	if( pthread_mutex_init(&hLogMutex,NULL) != 0 )
//#else
//	if( ( hLogMutex = CreateMutex(NULL, FALSE, NULL) ) == NULL )
//#endif
//	{
//		WriteFileLog(LFATAL,"Create a mutex lock for log module fails, the program terminates.");
//		exit(-1);
//	}        

	if( IsDelete )
	{
		if( CreateThreadWithArg(ThreadDeleteFile,NULL) == 0 )
		{
			WriteFileLog(LFATAL,"Create expired log files delete thread fails.");
		} 
	}

	WriteFileLog(LHINT,"");

	return(0);
}

int DestroyLogging()
{
	if( IsDelete )
	{
		status_del = 0;
		WriteFileLog(LHINT,"Delete file thread has ended");
	}

	gLogSrvOk = 0;
	gLogInit = 0;

    #if defined(LINUX)
	sleep(1);
    #else
	Sleep(1000);
    #endif

 //   #if defined(LINUX)
	//pthread_mutex_destroy(&hLogMutex);
 //   #else
	//CloseHandle(hLogMutex);
 //   #endif

    #if !defined(LINUX)
	WSACleanup();
    #endif

	return(1);
}

int GetLogInit()
{
	return(gLogInit);
}

void WriteFileLog( int eiLine, char *epczFile, int eiLevel, char *epczFmt, ... )
{
	int  isok;
	char aczStr[20480];
	char aczFile[1024];
	char aczLevel[15];
	char aczTemp[20480];
	int  wYear,wMonth,wDay,wHour,wMinute,wSecond;
	time_t   timep;
	struct   tm *p;
	va_list  vag;
	FILE     *fp=NULL;

	if( gLogInit == 0 )
	{
		return;
	}

	isok = 0;

 //   #if defined(LINUX)
	//pthread_mutex_lock(&hLogMutex);
 //   #else
	//WaitForSingleObject(hLogMutex, INFINITE);
 //   #endif

	time(&timep);
	p = localtime(&timep);
	wYear   = p->tm_year + 1900;
	wMonth  = p->tm_mon + 1;
	wDay    = p->tm_mday;
	wHour   = p->tm_hour;
	wMinute = p->tm_min;
	wSecond = p->tm_sec;
	if( eiLevel > gLoglevel ) 
	{
  //      #if defined(LINUX)
		//pthread_mutex_unlock(&hLogMutex);
  //      #else
		//ReleaseMutex(hLogMutex);
  //      #endif

		return;
	}

	memset( aczStr, 0, sizeof(aczStr) );
	memset( aczFile, 0, sizeof(aczFile) );
	memset( aczLevel, 0, sizeof(aczLevel) );
	memset( aczTemp, 0, sizeof(aczTemp) );

	if( gLogMode & 0x02 )
	{
		snprintf(aczFile,1024,"%s/%s%04d%02d%02d.log",gLogDir,gAppName,wYear, wMonth, wDay );
		if( (fp = fopen( aczFile, "a+" ))==NULL )
		{
			isok = 0 ;
		}
		else
		{
			isok = 1;
		}
	}

	switch( eiLevel ) 
	{
	case LEVEL_FATAL: 
		sprintf( aczLevel, "FATAL" );
		break;
	case LEVEL_ERROR:
		sprintf( aczLevel, "ERROR" );
		break;
	case LEVEL_WARN:
		sprintf( aczLevel, "WARN " );
		break;
	case LEVEL_HINT:
		sprintf( aczLevel, "HINT " );
		break;
	case LEVEL_DEBUG:
		sprintf( aczLevel, "DEBUG" );
		break;
	}

	va_start( vag, epczFmt );
	vsnprintf( aczStr,sizeof(aczStr),epczFmt, vag );
	va_end( vag );

	snprintf( aczTemp,sizeof(aczTemp),"%02d:%02d:%02d %s %-5d in %-15s %s\n", wHour, wMinute, wSecond, aczLevel, eiLine, GetFileName(epczFile), aczStr );
	if( gLogMode & 0x01 )
	{
		printf("%s", aczTemp );
	}
	if( ( gLogMode & 0x02 ) && ( isok == 1 ) ) 
	{
		fprintf( fp, "%s", aczTemp );
		fflush(fp);
		fclose(fp);
	}

    #if !defined(LINUX)
    if( pList )
	{
		pList->AddString(aczTemp);
		pList->SetCurSel(pList->GetCount()-1);
	}
    #endif

 //   #if defined(LINUX)
	//pthread_mutex_unlock(&hLogMutex);
 //   #else
	//ReleaseMutex(hLogMutex);
 //   #endif

	return;
}

void ProgramStartsRecording()
{
	char     aczFile[1024];
	int      wYear,wMonth,wDay,wHour,wMinute,wSecond;
	time_t   timep;
	struct   tm *p;
	FILE     *fp=NULL;

	if( gLogInit == 0 )
	{
		return;
	}

	time(&timep);
	p = localtime(&timep);
	wYear   = p->tm_year + 1900;
	wMonth  = p->tm_mon + 1;
	wDay    = p->tm_mday;
	wHour   = p->tm_hour;
	wMinute = p->tm_min;
	wSecond = p->tm_sec;

	snprintf(aczFile,1024,"%s/%s.rec",gLogDir,gAppName );

	if( (fp = fopen( aczFile, "a+" )) == NULL )
	{
		return;
	}

	fprintf( fp, "At %04d-%02d-%02d %02d:%02d:%02d the program starts in \n", wYear, wMonth, wDay, wHour, wMinute, wSecond);

	fflush(fp);

	fclose(fp);
}

char *GetAppVersion()
{
	return gVersion;
}

void SetVersion(char *ver)
{
	int len;
	len = strlen(ver); 
	if( ( len < 1 ) || ( len > 100 ) )
	{
		memset(gVersion,0,sizeof(gVersion));
	}
	else
	{
		memcpy(gVersion,ver,len+1);
	}
}

int GetBigEndian()
{
	return gBigEndian;
}

int GetLogLevel()
{
	return gLoglevel;
}

void SetLogLevel( int lev )
{
	if( ( lev < 0 ) || ( lev > 4 ) ) 
	{
		gLoglevel = 4;
	}
	else
	{
		gLoglevel = lev;
	}
}

int GetLogMode()
{
	return gLogMode;
}

void SetLogMode( int out )
{
	out = out & 0x07 ; 
	gLogMode = out;
}

short GetLogIpNum()
{
	return gLogIpNum;
}

void SetLogIpNum( short num )
{
	gLogIpNum = num;
}

unsigned short GetLogPort()
{
	return gLogPort;
}

void SetLogPort( unsigned short port )
{
	gLogPort = port;
}

char *GetConfigFile()
{
	return gAppConfigFile;
}

char *GetLogDir()
{
	return gLogDir;
}

void SetLogDir(char *dir)
{
	int len;
	len = strlen(dir); 
	if( ( len < 1 ) || ( len > 1023 ) )
	{
		return;
	}
	else
	{
		memcpy(gLogDir,dir,len+1);
	}
}

int GetDelete()
{
	return IsDelete;
}

void SetDelete( int is )
{
	if( is == 0 )
	{
		IsDelete = 0;
	}
	else
	{
		IsDelete = 1;
	}
}

long GetDeleteTime()
{
	return delTime;
}

void SetDeleteTime( int day )
{
	delTime = day * 24 * 3600;
}

char *GetAppPath()
{
	return gAppPath;
}

char *GetAppName()
{
	return gAppName;
}

char *GetAppIp()
{
	return(gLocalIp);
}

char *GetAppMac()
{
	return(gLocalMac);
}

//void GetNetInfo(short *num,char **name,char **ip,char **mac)
//{
//	*num = *gNetNum;
//	if( name )
//	{
//		name = gNetName;
//	}
//	if( ip )
//	{
//		ip = gNetIp;
//	}
//	if( mac )
//	{
//		mac = gNetMac;
//	}
//}

double GetTimeVal()
{
    #if defined(LINUX)
	struct timeval val;
	gettimeofday(&val, NULL);
	return((double)val.tv_sec + (double)val.tv_usec/1000000.0);
    #else  //-----------------------------------------------
	time_t clock;
	struct tm tm;
	SYSTEMTIME wtm;
	GetLocalTime(&wtm);
	tm.tm_year    = wtm.wYear - 1900;
	tm.tm_mon     = wtm.wMonth - 1;
	tm.tm_mday    = wtm.wDay;
	tm.tm_hour    = wtm.wHour;
	tm.tm_min     = wtm.wMinute;
	tm.tm_sec     = wtm.wSecond;
	tm.tm_isdst   = -1;
	clock = mktime(&tm);
	return((double)clock + (double)wtm.wMilliseconds/1000.0);
    #endif
}

char *GetDateTimeString(time_t now)
{
	static char strtime[30];
	struct tm *p;
	int    wYear,wMonth,wDay,wHour,wMinute,wSecond;    
	p = localtime(&now);
	wYear   = p->tm_year + 1900;
	wMonth  = p->tm_mon + 1;
	wDay    = p->tm_mday;
	wHour   = p->tm_hour;
	wMinute = p->tm_min;
	wSecond = p->tm_sec;
	memset(strtime,0,sizeof(strtime));
	sprintf(strtime,"%04d-%02d-%02d %02d:%02d:%02d",wYear, wMonth, wDay, wHour, wMinute, wSecond);
	return(strtime);
}

char *GetTimeString(double now)
{
	static char strtime[30];
	struct tm *p;
	int    wYear,wMonth,wDay,wHour,wMinute,wSecond;
	time_t  now1;
	double  now2;
	now1 = (time_t)now;
	now2 = now-now1;
	p = localtime(&now1);
	wYear   = p->tm_year + 1900;
	wMonth  = p->tm_mon + 1;
	wDay    = p->tm_mday;
	wHour   = p->tm_hour;
	wMinute = p->tm_min;
	wSecond = p->tm_sec;
	memset(strtime,0,sizeof(strtime));
	sprintf(strtime,"%02d:%02d:%02d:%03d", wHour, wMinute, wSecond, (int)(now2*1000));
	return(strtime);
}

char *GetTimeDelay(int delay)
{
	static char strtime[30];
	int    wHour,wMinute,wSecond;
	wHour   = delay/3600;
	wMinute = (delay%3600)/60;
	wSecond = (delay%3600)%60;
	memset(strtime,0,sizeof(strtime));
	sprintf(strtime,"%02d:%02d:%02d", wHour, wMinute, wSecond);
	return(strtime);
}

time_t string2time(const char * str)
{
	struct tm tm1;
	int year,mon,mday,hour,min,sec;
	if( sscanf(str,"%d-%d-%d %d:%d:%d",&year,&mon,&mday,&hour,&min,&sec) == -1 )
	{
		return 0;
	}
	tm1.tm_year=year-1900;
	tm1.tm_mon=mon-1;
	tm1.tm_mday=mday;
	tm1.tm_hour=hour;
	tm1.tm_min=min;
	tm1.tm_sec=sec;
	return mktime(&tm1);
}

int IncludeChinese(char *str)
{
	char c;
	while(1)
	{
		c=*str++;
		if( c == 0 ) break;
		if( c&0x80 )
		{
			if( *str & 0x80 )
			{
				return 1;
			}
		}
	}
	return 0;
}

int PreCreatePath(const char *path)
{
	int   i,len;
	char  czTemp[2048];

	memset(czTemp, 0, sizeof(czTemp) );

	strcpy(czTemp,path);
	len = strlen(czTemp);
#if defined(LINUX)
	if( czTemp[len-1] != '/' )
#else
	if( czTemp[len-1] != '\\' )
#endif
	{
#if defined(LINUX)
		strcat(czTemp,"/");
#else
		strcat(czTemp,"\\");
#endif
	}
	len = strlen(czTemp);

	for(i=1;i<len;i++)
	{    
#if defined(LINUX)
		if(czTemp[i]=='/')
#else
		if(czTemp[i]=='\\')
#endif
		{    
			czTemp[i] = 0;
			if( !isPathExists(czTemp) )
			{
#if defined(LINUX)
				if( mkdir(czTemp,S_IRWXU|S_IRWXG|S_IRWXO) != 0 )
				{
					return(0);
				} 
				if( chmod(czTemp,0777) != 0 )
				{
					return(0);
				}
#else //--------------------------------------
				if( _mkdir(czTemp) != 0 )
				{
					return(0);
				} 
#endif
			}
#if defined(LINUX)
			czTemp[i] = '/';
#else
			czTemp[i] = '\\';
#endif
		}
	}
	return(1);
}

int PreCreatefile(const char *filename)
{
	int   i,len;
	char  czTemp[2048];

	memset(czTemp, 0, sizeof(czTemp) );

	strcpy(czTemp,filename);
	len = strlen(czTemp);

	for(i=1;i<len;i++)
	{    
#if defined(LINUX)
		if(czTemp[i]=='/')
#else
		if(czTemp[i]=='\\')
#endif
		{    
			czTemp[i] = 0;
			if( !isPathExists(czTemp) )
			{
#if defined(LINUX)
				if( mkdir(czTemp,S_IRWXU|S_IRWXG|S_IRWXO) != 0 )
				{
					return(0);
				} 
				if( chmod(czTemp,0777) != 0 )
				{
					return(0);
				}
#else
				if( _mkdir(czTemp) != 0 )
				{
					return(0);
				} 
#endif
			}
#if defined(LINUX)
			czTemp[i] = '/';
#else
			czTemp[i] = '\\';
#endif
		}
	}
	return(1);
}

int DeleteFileByName(const char *file)
{
	if(!remove(file))
	{
		return(1);
	}
	else
	{
		return(0);
	}
}

int isPathExists(const char *path)
{
	if( ( access(path,0) ) != 0 )
	{
		return(0);
	}
	else
	{
		return(1);
	}
}

int isProcessExists(const char *name)
{
#if defined(LINUX)
	FILE  *fp;
	int   count = 0; 
	char  buf[512],cmd[1024];
	if( strlen(name) > 512 )
	{
		return(-1);
	} 
	sprintf(cmd,"ps -ef | grep %s | grep -v \"grep\" | wc -l",name);
	if( ( fp = popen(cmd,"r") ) == NULL )
	{
		return(-2);
	}
	if( (fgets(buf,500,fp) ) != NULL )
	{
		count = atoi(buf); 
	} 
	pclose(fp); 
	return(count);
#else  //----------------------------------------------
	return(0);
#endif
} 

int GetSubstr(char *sou,char *begin,char *end,char *des,long maxlen)
{
	long  len;
	char  *keyStart,*keyEnd;

	keyStart = strstr(sou, begin);
	if( keyStart<=0 )
	{
		return(-1);
	}
	keyStart += strlen(begin);

	keyEnd = strstr(keyStart, end);
	if( keyEnd<=0 )
	{
		return(-2);
	}
	keyEnd -= 1;

	len = keyEnd-keyStart+1;
	if( (len<0) || (len>=maxlen) )
	{
		return(-3);
	}
	memcpy(des, keyStart, len);
	des[len]='\0';
	return(len);
}

//封装字符串分割split函数
int Split(char *src, const char *separator, char **dest, int *num) 
{
	/*
		src 源字符串的首地址(buf的地址)
		separator 指定的分割字符
		dest 接收子字符串的数组
		num 分割后子字符串的个数
	*/
	char *pNext;
	int count = 0;
	if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0，直接终止 
		return -1;
	if (separator == NULL || strlen(separator) == 0) //如未指定分割的字符串，直接终止 
		return -1;
	pNext = (char *)strtok(src, separator); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
	while (pNext != NULL) {
		*dest++ = pNext;
		++count;
		pNext = (char *)strtok(NULL, separator);  //必须使用(char *)进行强制类型转换
	}
	*num = count;
	return 0;
}

//字符串替换函数
char * replace (const char *str, const char *src, const char *dst)
{
    const char* pos = str;
    int count = 0;
    while ((pos = strstr (pos, src))) {
        count ++;
        pos += strlen(src);
    }

    size_t result_len = strlen(str) + (strlen(dst) - strlen(src)) * count + 1;
    char *result = (char *)malloc(result_len);
    memset (result, 0, result_len);

    const char *left = str;
    const char *right = NULL;

    while ((right = strstr(left, src))) {
        strncat (result, left, right - left);
        strcat (result, dst);
        right += strlen(src);
        left = right;
    }
    strcat(result, left);
    return result;
}

static void GetAppInfo()
{
	int  i,j;
	char cz[1024];
	memset(cz,0,sizeof(cz));
	memset(gAppPath,0,sizeof(gAppPath));
	memset(gAppName,0,sizeof(gAppName));
#if defined(LINUX)
	readlink ("/proc/self/exe", cz, 1020);
#else
	GetModuleFileName( NULL, cz, 1020 );
#endif
	strcpy(gAppPath,cz);
	j = strlen(gAppPath);
	for(i=j-1;i>0;i--)
	{
#if defined(LINUX)
		if(gAppPath[i]=='/')
#else
		if(gAppPath[i]=='\\')
#endif
		{
			gAppPath[i]='\0';
			break;
		}
	}
	strcpy(gAppName,cz+strlen(gAppPath)+1);

#if defined(LINUX)
	j = strlen(gAppName);
	for(i=j-1;i>0;i--)
	{
		if(!isascii(gAppName[i]))
		{
			gAppName[i]='\0';
			break;
		}
	}
#else
	j = strlen(gAppName);
	for(i=j-1;i>0;i--)
	{
		if(gAppName[i]=='.')
		{
			gAppName[i]='\0';
			break;
		}
	}
#endif
}

static void *ThreadDeleteFile(void *param)
{
	status_del = 1;
	while(status_del)
	{
		DeleteExpiredFile(gLogDir,(long)delTime);
		if( status_del )
		{
#if defined(LINUX)
			sleep(10);
#else
			Sleep(10000);
#endif
		}
	}
	return(NULL);
}

static void DeleteExpiredFile(char *path,long expsec)
{  
#if defined(LINUX)
	//struct timeval   val;
	struct stat      buf;   
	long             cursec;
	DIR              *pDir;
	struct dirent    *ent;            
	char             *p,childpath[1024];

	if( (pDir=opendir(path)) == NULL )
	{
		return;
	}

	//gettimeofday(&val, NULL);
	//cursec = val.tv_sec ;
	cursec = (long)GetTimeVal();

	memset(childpath,0,sizeof(childpath));

	while((ent=readdir(pDir))!=NULL) 
	{  
		if(ent->d_type & DT_DIR)  //如果读取的d_type类型为DT_DIR (=4 表示读取的为目录)
		{  
			if( ( strcmp(ent->d_name,".") == 0 ) || ( strcmp(ent->d_name,"..") == 0 ) )
			{
				continue;
			}
			sprintf(childpath,"%s/%s",path,ent->d_name);
			DeleteExpiredFile(childpath,expsec);
		}  
		else
		{
			sprintf(childpath,"%s/%s",path,ent->d_name);
			if( stat(childpath,&buf) != 0 )
			{
				continue;
			}
			p = strstr(childpath,".log");
			if( ( p <= 0 ) || ( strlen(p) > 4 ) )
			{
				continue;
			}

			if( (cursec - buf.st_mtime) > expsec )
			{
				WriteFileLog(LDEBUG,"Delete file(%s)!",childpath);
				remove(childpath);
			}
		}
	}  
	closedir(pDir);
#else   //-------------------Windows-----------------------------
	long             cursec;
	WIN32_FIND_DATA  tempFind;
	HANDLE           hFind;
	struct stat      buf;   
	char             *p,tempDir[1024];

	cursec = (long)GetTimeVal();
	sprintf(tempDir,"%s\\*.*",path);
	if( ( hFind = FindFirstFile(tempDir, &tempFind) ) == INVALID_HANDLE_VALUE )
	{
		return;
	}

	do
	{
		if( tempFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
		{                       
			if( ( strcmp(tempFind.cFileName,".") == 0 ) || ( strcmp(tempFind.cFileName,"..") == 0 ) )
			{
				continue;
			}
			sprintf(tempDir,"%s\\%s",path,tempFind.cFileName);
			DeleteExpiredFile(tempDir,expsec);
		}
		else
		{       
			sprintf(tempDir,"%s\\%s",path,tempFind.cFileName);
			if( stat(tempDir,&buf) != 0 )
			{
				continue;
			}
			p = strstr(tempDir,".log");
			if( ( p <= 0 ) || ( strlen(p) > 4 ) )
			{
				continue;
			}
			if( (cursec - buf.st_mtime) > expsec )
			{
				WriteFileLog(LHINT,"Delete file(%s)!",tempDir);
				remove(tempDir);
			}
		}
	}   while( FindNextFile(hFind, &tempFind) );
	FindClose(hFind);
#endif
}  

int ReadCfgItem( char const *file,char const *item,char *buf)
{
	FILE * fp;
	char *dest,*p,cz[1024],str[1024];
	if((fp = fopen(file, "r")) == NULL)
	{
		return(-1);
	}
	dest = NULL;
	memset(str,0,1024);
	while(fgets(str,1023,fp) != NULL )
	{
		if( str[0] == '#' )
		{
			continue;
		}
		str[strlen(str)-1] = '\0';
		if( ( p = strstr(str,"=") ) == NULL )
		{
			continue;
		}
		memset(cz,0,sizeof(cz));
		memcpy(cz,str,p-str);
		cz[p-str+1] = '\0';
		strcpy(cz,mytrim(cz));
		if ( strcmp(item,cz) == 0 )
		{
			p++;
			strcpy(buf, mytrim(p));
			fclose(fp);
			return (0);
		}
	}
	fclose(fp);
	return -2;
}

int CheckBigEndian()
{
	unsigned short thenumber=0xaabb;
	if( *((unsigned char *)&thenumber) == 0xaa )
	{
		return(1);
	}
	else
	{
		return(0);
	}
}

int CheckIPCorrect(char *ip)
{
	int i,j,len;
	len = strlen(ip);
	if( len > 15 )
	{
		return(-1);
	}
	j = 0;
	for(i=0;i<len;i++)
	{
		if( ip[i] == '.' )
		{
			j++;
		}
	}
	if( j != 3 )
	{
		return(-2);
	}
	if( inet_addr(ip) == INADDR_NONE )
	{
		return(-3);
	}
	return(0);
}

int GetFileSizeByName(const char* file)
{
    struct stat tbuf;
    if( stat(file, &tbuf) )
	{
		return(-1);
	}
	else
	{
		return tbuf.st_size;
	}
}


char *GetFileName(char *path)
{
	char *pos;
	pos = path + strlen(path);
	#if defined(LINUX)
	while( ( *pos != '/' ) && ( pos != path ) )
	#else
	while( ( *pos != '\\' ) && ( pos != path ) )
	#endif
	{
		pos --;
	}
	if( pos == path )
	{
		return path;
	}
	else
	{
		return( pos + 1 );
	}
}



#if defined(LINUX)

//struct if_nameindex 
//{
//    unsigned int   if_index;
//    char          *if_name;
//};  //结构提
static char *bad_interface_names[] = 
{
	"lo:",
	"lo",
	"stf",     // pseudo-device 6to4 tunnel interface 
	"gif",     // psuedo-device generic tunnel interface 
	"dummy",
	"vmnet",
	NULL       // last entry must be NULL 
};
static int is_bad_interface_name(char *i) 
{
	char **p;
	for(p = bad_interface_names; *p; ++p)
	{
		if( strncmp(i, *p, strlen(*p)) == 0 )
		{
			return 1;
		}
	}
	return 0;
}
//// This finds the first interface which is up and is not the loopback
//// interface or one of the interface types listed in bad_interface_names.
//char *GetIfrname(void) 
//{
//	static char ifname[250];
//	struct if_nameindex * nameindex;
//	int j = 0;
//	// Use if_nameindex(3) instead? 
//
//	memset(ifname,0,sizeof(ifname));
//
//	nameindex = if_nameindex();
//	if(nameindex == NULL) 
//	{
//		return NULL;
//	}
//	while(nameindex[j].if_index != 0) 
//	{
//		if(strcmp(nameindex[j].if_name, "lo") != 0 && !is_bad_interface_name(nameindex[j].if_name)) 
//		{
//			strncpy(ifname,nameindex[j].if_name,20);
//			break;
//		}
//		j++;
//	}
//	if_freenameindex(nameindex);
//
//	return ifname;
//}
//
#endif

void WaitNetworkUp()
{
	while( GetNetworkInfo() < 0 )
	{
		WriteFileLog(LWARN,"The network is not ready, please wait!");
#if defined(LINUX)
		sleep(1);
#else
		Sleep(1000);
#endif
	}
	WriteFileLog(LHINT,"The network is ready!");
	DisplayNetworkInfo();
}

int GetNetworkInfo()
{
#if defined(LINUX)
	struct if_nameindex *nameindex;

	if( ( nameindex = if_nameindex() ) == NULL )
	{
		return(-1);
	}

	gNetNum = 0;

	int j = 0;
	while(nameindex[j].if_index != 0) 
	{
		if(strcmp(nameindex[j].if_name, "lo") != 0 && !is_bad_interface_name(nameindex[j].if_name)) 
		{
			int       sockfd;
			struct    ifreq ifr;
			struct    sockaddr_in cz;
			unsigned  char czMac[20];

			//WriteFileLog(LHINT,"Find the %d network adapter card.",gNetNum+1);

			memset(gNetName[gNetNum],0,sizeof(gNetName[gNetNum]));
			memset(gNetIp[gNetNum],0,sizeof(gNetIp[gNetNum]));
			memset(gNetMac[gNetNum],0,sizeof(gNetMac[gNetNum]));

			if( ( sockfd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0 )
			{
				if_freenameindex(nameindex);
				if( gNetNum == gLogIpNum )
				{
					return(-2 - gNetNum*10);
				}
				else
				{
					return(0);
				}
			}
			strcpy(gNetName[gNetNum],nameindex[j].if_name);
			strcpy(ifr.ifr_name,nameindex[j].if_name); 
			//WriteFileLog(LHINT,"Find the name=%s at %d network adapter card.",gNetName[gNetNum],gNetNum+1);

			if( ioctl(sockfd, SIOCGIFADDR, &ifr) < 0 )
			{
				Close(sockfd);
				if_freenameindex(nameindex);
				if( gNetNum == gLogIpNum )
				{
					return(-3 - gNetNum*10);
				}
				else
				{
					return(0);
				}
			}
			cz.sin_addr = ((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr;
			strcpy( gNetIp[gNetNum] , inet_ntoa( cz.sin_addr ));
			//WriteFileLog(LHINT,"Find the ip=%s at %d network adapter card.",gNetIp[gNetNum],gNetNum+1);

			if( ioctl( sockfd, SIOCGIFHWADDR, &ifr) < 0 )
			{
				Close(sockfd);
				if_freenameindex(nameindex);
				if( gNetNum == gLogIpNum )
				{
					return(-6 - gNetNum*10);
				}
				else
				{
					return(0);
				}
			}
			memcpy(czMac,ifr.ifr_hwaddr.sa_data,6);
			snprintf(gNetMac[gNetNum],19,"%02x:%02x:%02x:%02x:%02x:%02x",czMac[0],czMac[1],czMac[2],czMac[3],czMac[4],czMac[5]);
			//WriteFileLog(LHINT,"Find the mac=%s at %d network adapter card.",gNetMac[gNetNum],gNetNum+1);

			Close(sockfd);

			gNetNum++;
		}
		j++;
	}
	if_freenameindex(nameindex);

#else

	unsigned short i;
	PHOSTENT hostinfo; 
	char     m_HostName[256]; 

	memset(m_HostName,0,sizeof(m_HostName));

	if( gethostname ( m_HostName,sizeof(m_HostName)) == SOCKET_ERROR ) 
	{
		return(-2);
	}

	if( ( hostinfo = gethostbyname(m_HostName) ) == NULL ) 
	{
		return(-3);
	}

	gNetNum = 0;

	for(i=0;*(hostinfo->h_addr_list+i);i++)
	{
		unsigned long ipAddr;
		ULONG pulMac[2];
		ULONG ulLen;

		memset(gNetName[gNetNum],0,sizeof(gNetName[gNetNum]));
		memset(gNetIp[gNetNum],0,sizeof(gNetIp[gNetNum]));
		memset(gNetMac[gNetNum],0,sizeof(gNetMac[gNetNum]));

		strncpy(gNetName[gNetNum],hostinfo->h_name,249);

		snprintf(gNetIp[gNetNum],19,"%s",inet_ntoa (*(struct in_addr *)*(hostinfo->h_addr_list+i)));
		ipAddr = inet_addr(gNetIp[gNetNum]);
		memset(pulMac,0xff,sizeof(pulMac));
		ulLen = 6;
		HRESULT  hr = SendARP(ipAddr,0,pulMac,&ulLen);
		PBYTE pbHexMac = (PBYTE)pulMac;
		if(hr== NO_ERROR)
		{
			snprintf(gNetMac[gNetNum],19,"%02X-%02X-%02X-%02X-%02X-%02X",pbHexMac[0],pbHexMac[1],pbHexMac[2],pbHexMac[3],pbHexMac[4],pbHexMac[5]);
		}
		else
		{
			snprintf(gNetIp[gNetNum],19,"");
		}
		gNetNum++;
	}

#endif

	return(0);
}

void DisplayNetworkInfo()
{
	int i;
	WriteFileLog(LHINT,"gNetNum = %d",gNetNum);
	for(i=0;i<gNetNum;i++)
	{
		WriteFileLog(LHINT,"gNetName[%d] = %s gNetIp[%d] = %s gNetMac[%d] = %s",i,gNetName[i],i,gNetIp[i],i,gNetMac[i]);
	}
}

#if defined(LINUX)
pthread_t CreateThreadWithArg(void *(*func)(void *), void *arg)
#else
HANDLE CreateThreadWithArg(void *(*func)(void *), void *arg)
#endif
{
    #if defined(LINUX)
	pthread_attr_t      attr;
	pthread_t           thread;
	//struct sched_param  param;
	//sched_getparam(0, &param);
	//param.sched_priority = sched_get_priority_max(SCHED_FIFO);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	//pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
	//pthread_attr_setschedparam(&attr, &param);
	if( pthread_create(&thread, &attr, func, arg) != 0 )
	{
		pthread_attr_destroy(&attr);
		return(0);
	}
	pthread_attr_destroy(&attr);
	return(thread);
    #else
	HANDLE handle;
	if( ( handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL) ) == NULL )
	{
		return(0);
	}
	return(handle);
    #endif
}

//
// --------------------------------------------------------------------------------
// 编码转换
//

//定义查找表，长度256，表中的数值表示以此为起始字节的utf8字符长度
unsigned char utf8_look_for_table[] =
{
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};

#define UTFLEN(x)  utf8_look_for_table[(x)]

int GetUtf8Length(const char *str)
{
	int  clen;
	int  len = 0;

	clen = strlen(str);

	while( ( *str != 0 ) && ( len < clen ) )
	{
		len++;
		str += UTFLEN( (unsigned char)*str );
	}
	return len;
}

char *GB18030ToUTF_8(const char *pGBKstr,int gbkLen,char *pUTF8str,int *utf8Len)
{
	char buf[1024];
	//char *pUTF8str = new char[gbkLen+(gbkLen>>2)+2];
	memset(buf,0,1024);
	//memset(pUTF8str,0,gbkLen+(gbkLen>>2)+2);
	int i = 0;
	int j = 0;
	while(i < gbkLen)
	{
		if( *(pGBKstr + i) >= 0)
		{
			pUTF8str[j++] = pGBKstr[i++];
		}
		else
		{
			wchar_t pbuffer;
			GB18030ToUnicode(&pbuffer,pGBKstr+i);
			UnicodeToUTF_8(buf,&pbuffer);
			unsigned short int tmp = 0;
			tmp = pUTF8str[j] = buf[0];
			tmp = pUTF8str[j+1] = buf[1];
			tmp = pUTF8str[j+2] = buf[2];
			j+= 3;
			i+= 2;
		}
	}
	*utf8Len = j;
	strcpy(&pUTF8str[j],"\0\0");
	return pUTF8str;
}

void GB18030ToUnicode(wchar_t *pOut,const char *gbBuffer)
{
    #if defined(LINUX)
	mbstowcs(pOut,gbBuffer,2);
    #else
	::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
    #endif
}

void UnicodeToUTF_8(char *pOut,wchar_t *pText)
{
	char *pchar = (char *)pText;
	pOut[0] = (0xE0|((pchar[1]&0xF0)>>4));
	pOut[1] = (0x80|((pchar[1]&0x0F)<<2))+((pchar[0]&0xC0)>>6);
	pOut[2] = (0x80|(pchar[0]&0x3F));
}

char *UTF_8ToGB18030(const char *pUTF8str,int utf8Len,char *pGBKstr,int *gbkLen)
{
	//char *pGBKstr = new char[utf8Len];
	char Ctemp[4];
	memset(Ctemp,0,4);

	int i =0;
	int j = 0;

	while( i < utf8Len )
	{
		if( pUTF8str[i] > 0 )
		{
			pGBKstr[j++] = pUTF8str[i++];
		}
		else
		{
			wchar_t Wtemp;

			UTF_8ToUnicode(&Wtemp,pUTF8str+i);
			UnicodeToGB18030(Ctemp,(unsigned short *)&Wtemp);

			pGBKstr[j] = Ctemp[0];
			pGBKstr[j+1] = Ctemp[1];  

			i += 3;
			j += 2;
		}
	}
	strcpy(&pGBKstr[j],"\0\0");
	return pGBKstr;
}

void UTF_8ToUnicode(wchar_t *pOut,const char *pText)
{
	char *uchar = (char *)pOut;
	uchar[1] = ((pText[0]&0x0F)<<4)+((pText[1]>>2)&0x0F);
	uchar[0] = ((pText[1]&0x03)<<6)+(pText[2]&0x3F);
}

void UnicodeToGB18030(char *pOut,unsigned short *uData)
{
#if defined(LINUX)
	wcstombs(pOut,(wchar_t *)uData,10);
#else
	::WideCharToMultiByte(CP_ACP,NULL,LPCWSTR(uData),1,pOut,sizeof(WCHAR),NULL,NULL);
#endif
}

// 
//
// --------------------------------------------------------------------------------
// 编码转换
//
// @brief URLEncode 对字符串URL编码 
// 
// @param str 原字符串 
// @param strSize 原字符串长度(不包括最后的\0) 
// @param result 结果缓冲区的地址
// @param resultSize 结果缓冲区的大小(包括最后的\0)
//
// @return: >0:resultstring 里实际有效的长度
//            0: 解码失败
//
int URLEncode(const char* str, const int strSize, char* result, const int resultSize)
{
	int i;
	int j = 0;  //for result index
	char ch;

	if ((str==NULL) || (result==NULL) || (strSize<=0) || (resultSize<=0))
	{
		return 0;
	}

	for ( i=0; (i<strSize)&&(j<resultSize); ++i)
	{
		ch = str[i];  
		if( ((ch>='A') && (ch<'Z')) || ((ch>='a') && (ch<'z')) || ((ch>='0') && (ch<'9')) )
		{
			result[j++] = ch;
		}
		else if( ch == ' ' )
		{
			result[j++] = '+';
		} 
		else if( ch == '.' || ch == '-' || ch == '_' || ch == '*' )
		{  
			result[j++] = ch;
		} 
		else 
		{  
			if( ( j+3 ) < resultSize )
			{
				sprintf(result+j, "%%%02X", (unsigned char)ch);
				j += 3;
			} 
			else 
			{
				return 0;
			}
		}
	}

	result[j] = '\0';
	return j;
}

// 字符串转long long类型
long long myatoll(char *instr)
{
	long long retval;

	retval = 0;

	for( ; *instr ; instr++ )
	{
		retval = 10*retval + (*instr - '0');
	}
	return retval;
}

// 字符串头尾修剪函数
char *mytrim(char *str)
{
	char *head,*tail=NULL;
	if( str == NULL )
	{
		return str;
	}
	for( head = str ; *str ; str++ )
	{
		if( ( *str != ' ' ) && ( *str != '\t' ) && ( *str != '\r' ) && ( *str != '\n' ) && ( *str != '\f' ) && ( *str != '\b' ) )
		{
			if( tail == NULL)
			{
				head = str;      // tail为NULL时，此处为第一个非空格字符，将此位置保存下来
			}
			tail = str+1;        // 更新tail指针的指向为非空格字符的下一个位置
		}
	}
	if( tail )                   // 由于tail始终指向非空格字符的下一个位置，当循环退出时，tail指向右边第一个空格
	{
		*tail = 0;
	}
	else
	{
		*head = 0;
	}
	return head;
}

// 字符串头尾修剪函数
char *mytrim1(char *str)
{
	int i,j;
	int len = strlen(str);
	if( len == 0 )
	{
		return(str);
	}
	for(i=0;i<len;i++)
	{
		if( ( *(str+i) != ' ' ) && ( *(str+i) != '\t' ) && ( *(str+i) != '\r' ) && ( *(str+i) != '\n' ) && ( *(str+i) != '\f' ) && ( *(str+i) != '\b' ) )
		{
			break;
		}
	}
	for(j=len-1;j>=0;j--)
	{
		if( ( *(str+j) != ' ' ) && ( *(str+j) != '\t' ) && ( *(str+j) != '\r' ) && ( *(str+j) != '\n' ) && ( *(str+j) != '\f' ) && ( *(str+j) != '\b' ) )
		{
			break;
		}
	}
	*(str+j+1) = '\0' ;
	return(str+i);
}

// 与Json不兼容的特殊字符过滤函数
//char *JsonIllegalCharFilter(char *s)
//{
//    int i,j;
//    j = 0;
//    for(i=0;s[i]!='\0';i++)
//    {
//        if( ( s[i] != '\r' ) && ( s[i] != '\n' ) && ( s[i] != '{' ) && ( s[i] != '}' ) && ( s[i] != '[' ) && ( s[i] != ']' ) && ( s[i] != ',' ) && ( s[i] != '\b' ) && ( s[i] != '\f' ) && ( s[i] != '\t' ) && ( s[i] != '\\' ) && ( s[i] != '/' ) )
//        {
//            s[j++] = s[i];
//        }
//    }
//    s[j] = '\0';
//    return(s);
//}
char *JsonIllegalCharFilter(char *s)
{
	long i,j;
	j = 0;
	for(i=0;s[i]!='\0';i++)
	{
		switch( s[i] )
		{
		case '\b':
			break;
		case '\f':
			break;
		case '\n':
			break;
		case '\r':
			break;
		case '\t':
			break;
		case '\"':
			break;
		case '\'':
			break;
		case '\\':
			break;
		case '/':
			break;
		case '{':
			break;
		case '}':
			break;
		case '[':
			break;
		case ']':
			break;
		case ',':
			break;
		case ':':
			break;
		case '<':
			break;
		case '>':
			break;
		case '&':
			break;
		default:
			s[j++] = s[i];
			break;
		}
	}
	s[j] = '\0';
	// 过滤 ·
	stringFilter(s,"·");
	return(s);
}

char *stringFilter(char *sou,char *sfi)
{
	long i,j,len1,len2;
	len1 = strlen(sou);
	len2 = strlen(sfi);
	if( ( len1 <= 0 ) || ( len2 <= 0 ) || ( len1 < len2 ) )
	{
		return(sou);
	}

	j = 0;
	for(i=0;i<len1;i++)
	{
		if( ( (len1-len2-i) >= 0 ) && ( memcmp(sou+i,sfi,len2) == 0 ) )
		{
			i = i+len2-1;
		}
		else
		{
			sou[j++] = sou[i];
		}
	}
	sou[j] = '\0';
	return(sou);
}

// 检查是否有不兼容json的字符
int CheckJsonIllegalChar(char *s)
{
	int i;
	for(i=0;s[i]!='\0';i++)
	{
		if( ( s[i] == '\r' ) || ( s[i] == '\n' ) || ( s[i] == '{' ) || ( s[i] == '}' ) || ( s[i] == '[' ) || ( s[i] == ']' ) || ( s[i] == ',' ) || ( s[i] == '\b' ) || ( s[i] == '\f' ) || ( s[i] == '\t' ) || ( s[i] == '\\' ) || ( s[i] == '/' ) )
		{
			return(1);
		}
	}
	return(0);
}

int StringToHex(const char *src, int len, char *dst, int maxlen)
{
	if( src == NULL )
	{
		return -1;
	}
	if( dst == NULL )
	{
		return -2;
	}

    int  i;
	int  j = 0;
	int  ntmp = 0;
	char sztmp[3] = {0};

	for(i=0; i<len; i+=2 )
	{
		memcpy(sztmp, &(src[i]), 2);
		ntmp = strtol(sztmp, NULL, 16);

		if ( j > maxlen )
		{
			return -3;
		}
		dst[j] = ntmp & 0xff;
		j++;
	}
	dst[j] = 0;
	return j;
}

int HexToString(const char *src, int len, char *dst, int maxlen)
{
	if( src == NULL )
	{
		return -1;
	}
	if( dst == NULL )
	{
		return -2;
	}

    int  i;
	int  j = 0;
	char sztmp[3] = {0};

	unsigned char *psztmpSrc = (unsigned char *)src;

	memset(dst, 0, maxlen);

	for(i=0; i<len; i++)
	{
		sprintf(sztmp, "%02X", psztmpSrc[i]);
		j += 2;
		if ( j > maxlen )
		{
			return -3;
		}
		strncat(dst, sztmp, 2);
	}

	return 0;
}

void GetAddressNumeric(const char *ip, unsigned char *i1, unsigned char *i2, unsigned char *i3, unsigned char *i4)
{
    unsigned int a;
    a = ntohl(inet_addr(ip));
    *i1 = (unsigned char)((a >> 24) & 0x000000ff);
    *i2 = (unsigned char)((a >> 16) & 0x000000ff);
    *i3 = (unsigned char)((a >> 8 ) & 0x000000ff);
    *i4 = (unsigned char)((a      ) & 0x000000ff);
}

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr,int *stop)
{
	int n;
again:
	if( (n = accept(fd, sa, salenptr)) < 0 ) 
	{
#if defined(LINUX)
		if( ( errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN ) )
		{
			usleep(100000);
			if( *stop )
			{
				goto again;
			}
			else
			{
				return(0);
			}
		}
		else
		{
			return(-1);
		}
#else
		int err = WSAGetLastError();
		if( err == WSAEWOULDBLOCK ) 
		{
			Sleep(100);
			if( *stop )
			{
				goto again;
			}
			else
			{
				return(0);
			}
		}
		else
		{
			return(-1);
		}
#endif
	}
	return(n);
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
	if( bind(fd, sa, salen) < 0 )
	{
		WriteFileLog(LFATAL,"The bind function failed, the program terminates.");
		exit(1);
	}
}

void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
	if( connect(fd, sa, salen) < 0 )
	{
		WriteFileLog(LFATAL,"The connect function failed, the program terminates.");
		exit(1);
	}
}

void Getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlenptr)
{
	//#if defined(LINUX)
	//    if( getsockopt(fd, level, optname, optval, optlenptr) < 0 )
	//#else
	if( getsockopt(fd, level, optname, (char *)optval, optlenptr) < 0 )
		//#endif
	{
		WriteFileLog(LFATAL,"The getsockopt function failed, the program terminates.");
		exit(1);
	}
}

void Setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
{
	//#if defined(LINUX)
	//    if( setsockopt(fd, level, optname, optval, optlen) < 0 )
	//#else
	if( setsockopt(fd, level, optname, (char *)optval, optlen) < 0 )
		//#endif
	{
		WriteFileLog(LFATAL,"The setsockopt function failed, the program terminates.");
		exit(1);
	}
}

void Listen(int fd, int backlog)
{
	char    *ptr;
	if( (ptr = getenv("LISTENQ")) != NULL )
	{
		backlog = atoi(ptr);
	}
	if (listen(fd, backlog) < 0)
	{
		WriteFileLog(LFATAL,"The listen function failed, the program terminates.");
		exit(1);
	}
}

void Shutdown(int fd, int how)
{
	if( shutdown(fd, how) < 0 )
	{
		WriteFileLog(LFATAL,"The shutdown function failed, the program terminates.");
		exit(1);
	}
}

int Socket(int family, int type, int protocol)
{
	int n;
	if( (n = socket(family, type, protocol)) < 0 )
	{
		WriteFileLog(LFATAL,"The socket function failed, the program terminates.");
		exit(1);
	}
	return(n);
}


void *Calloc(size_t n, size_t size)
{
	void    *ptr;
	if( (ptr = calloc(n, size)) == NULL )
	{
		WriteFileLog(LFATAL,"The calloc function failed, the program terminates.");
		exit(1);
	}
	return(ptr);
}

void Close(int fd)
{
	if( fd == 0 )
	{
		//WriteFileLog(LERROR,"Can not close 0");
		return;
	}
    #if defined(LINUX)
	close(fd);
    #else
	closesocket(fd);
    #endif
}

//void Pthread_detach(pthread_t tid)
//{
//    int n;
//    if( (n = pthread_detach(tid)) != 0 )
//    {
//        WriteFileLog(LWARN,"The pthread_detach function failed : %s", strerror(errno));
//    }
//}

//int Fcntl(int fd, int cmd, int arg)
//{
//    int    n;
//    if( (n = fcntl(fd, cmd, arg)) == -1 )
//    {
//        WriteFileLog(LWARN,"The fcntl function failed, the program terminates.");
//        exit(1);
//    }
//    return(n);
//}

//int Ioctl(int fd, int request, void *arg)
//{
//    int        n;
//    if( (n = ioctl(fd, request, arg)) == -1 )
//    {
//        WriteFileLog(LFATAL,"The ioctl function failed, the program terminates.");
//        exit(1);
//    }
//    return(n);
//}

//pid_t Fork(void)
//{
//    pid_t    pid;
//    if( (pid = fork()) == -1 )
//    {
//        WriteFileLog(LFATAL,"The fork function failed, the program terminates.");
//        exit(1);
//    }
//    return(pid);
//}

void *Malloc(size_t size)
{
	void    *ptr;
	if( (ptr = malloc(size)) == NULL )
	{
		WriteFileLog(LFATAL,"The malloc function failed, the program terminates.");
		exit(1);
	}
	return(ptr);
}

int SetNonblockSocket(int fd)
{
    #if defined(LINUX)
	int flags = fcntl(fd,F_GETFL,0);
	if( fcntl(fd,F_SETFL,flags|O_NONBLOCK) < 0 )
	{
		return(-1);
	}
    #else
	unsigned long flags = 1;
	if( ioctlsocket(fd,FIONBIO,(unsigned long *)&flags) == SOCKET_ERROR )
	{
		return(-1);
	}
    #endif
	return(0);
}

int SetSOLINGEROn(int fd)
{
#if defined(LINUX)
	struct linger optval1;
	//设置SO_LINGER选项(防范CLOSE_WAIT挂住所有套接字)
	optval1.l_onoff = 1;
	optval1.l_linger = 0;
	setsockopt(fd, SOL_SOCKET, SO_LINGER, &optval1, sizeof(struct linger));
#else
	struct linger optval1;
	//设置SO_LINGER选项(防范CLOSE_WAIT挂住所有套接字)
	optval1.l_onoff = 1;
	optval1.l_linger = 0;
	setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&optval1, sizeof(struct linger));
#endif
	return(0);
}

size_t Writen(int fd, const void *vptr, size_t n)
{
	size_t         nleft;
	long           nwritten;
	const char     *ptr;

	ptr = (const char *)vptr;
	nleft = n;
	while( nleft > 0 ) 
	{
		if( (nwritten = write(fd, ptr, nleft)) <= 0 ) 
		{
			if( ( nwritten < 0 ) && ( errno == EINTR ) )
			{
				nwritten = 0;        // and call write() again 
			}
			else
			{
				WriteFileLog(LWARN,"The Writen() function failed.");
				return(0);          // error 
			}
		}
		nleft -= nwritten;
		ptr   += nwritten;
	}
	return(n);
}


int udp_client(const char *host, const char *serv, struct sockaddr *saptr, socklen_t *lenp)
{
	int				sockfd, n;
	struct addrinfo	hints, *res, *ressave;

	memset(&hints,0,sizeof(struct addrinfo));
	//hints.ai_family = AF_UNSPEC;
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_DGRAM;

	if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)
	{
		return(-1);
	}
	ressave = res;

	do 
	{
		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd >= 0)
		{
			break;		/* success */
		}
	}   while ( (res = res->ai_next) != NULL);

	if (res == NULL)	/* errno set from final socket() */
	{
		return(-2);
	}

	//*saptr = (struct sockaddr *)Malloc(res->ai_addrlen);
	memcpy(saptr, res->ai_addr, res->ai_addrlen);
	*lenp = res->ai_addrlen;

	freeaddrinfo(ressave);

	return(sockfd);
}

int udp_server(const char *host, const char *serv, socklen_t *addrlenp)
{
	int				sockfd, n;
	struct addrinfo	hints, *res, *ressave;

	memset(&hints,0,sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;

	if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)
	{
		return(-1);
	}

	ressave = res;

	do 
	{
		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd < 0)
		{
			continue;		/* error - try next one */
		}

		if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
		{
			break;			/* success */
		}

		Close(sockfd);		/* bind error - close and try next one */
	}   while ( (res = res->ai_next) != NULL);

	if (res == NULL)	/* errno from final socket() or bind() */
	{
		return(-2);
	}

	if (addrlenp)
	{
		*addrlenp = res->ai_addrlen;	/* return size of protocol address */
	}

	freeaddrinfo(ressave);

	return(sockfd);
}

int mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen,const char *ifname, u_int ifindex)
{
    #ifdef MCAST_JOIN_GROUP
	struct group_req req;
	if (ifindex > 0) 
	{
		req.gr_interface = ifindex;
	} 
	else if (ifname != NULL) 
	{
		if ( (req.gr_interface = if_nametoindex(ifname)) == 0) 
		{
			errno = ENXIO;	/* i/f name not found */
			return(-1);
		}
	} 
	else
	{
		req.gr_interface = 0;
	}

	if (grplen > sizeof(req.gr_group)) 
	{
		errno = EINVAL;
		return -1;
	}

	memcpy(&req.gr_group, grp, grplen);

	return (setsockopt(sockfd, family_to_level(grp->sa_family),MCAST_JOIN_GROUP, (char *)&req, sizeof(req)));
    #else
    /* end mcast_join1 */

	    /* include mcast_join2 */
	switch (grp->sa_family) 
	{
	case AF_INET: 
		{
			struct ip_mreq		mreq;
			struct ifreq		ifreq;

			memcpy(&mreq.imr_multiaddr,&((const struct sockaddr_in *) grp)->sin_addr,sizeof(struct in_addr));

			if (ifindex > 0) 
			{
				if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) {
					errno = ENXIO;	/* i/f index not found */
					return(-1);
				}
				goto doioctl;
			} 
			else if (ifname != NULL) 
			{
				strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
				doioctl:
				if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0)
				{
					return(-1);
				}
				memcpy(&mreq.imr_interface,&((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr,sizeof(struct in_addr));
			} 
			else
			{
				mreq.imr_interface.s_addr = htonl(INADDR_ANY);
			}

			return(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq)));
		}
        /* end mcast_join2 */

		/* include mcast_join3 */
		#ifdef	IPV6
		#ifndef	IPV6_JOIN_GROUP		/* APIv0 compatibility */
		#define	IPV6_JOIN_GROUP		IPV6_ADD_MEMBERSHIP
		#endif
	case AF_INET6: 
		{
			struct ipv6_mreq	mreq6;

			memcpy(&mreq6.ipv6mr_multiaddr,
				   &((const struct sockaddr_in6 *) grp)->sin6_addr,
				   sizeof(struct in6_addr));

			if (ifindex > 0) {
				mreq6.ipv6mr_interface = ifindex;
			} else if (ifname != NULL) {
				if ( (mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) {
					errno = ENXIO;	/* i/f name not found */
					return(-1);
				}
			} else
				mreq6.ipv6mr_interface = 0;

			return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
							  &mreq6, sizeof(mreq6)));
		}
        #endif

	default:
		errno = EAFNOSUPPORT;
		return(-1);
	}
    #endif
}
/* end mcast_join3 */

void Mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen,const char *ifname, u_int ifindex)
{
	mcast_join(sockfd, grp, grplen, ifname, ifindex);
}

int mcast_join_source_group(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen,const char *ifname, u_int ifindex)
{
    #ifdef MCAST_JOIN_SOURCE_GROUP
	struct group_source_req req;
	if (ifindex > 0) 
	{
		req.gsr_interface = ifindex;
	} 
	else if (ifname != NULL) 
	{
		if ( (req.gsr_interface = if_nametoindex(ifname)) == 0) 
		{
			errno = ENXIO;	/* i/f name not found */
			return(-1);
		}
	} 
	else
	{
		req.gsr_interface = 0;
	}

	if (grplen > sizeof(req.gsr_group) || srclen > sizeof(req.gsr_source)) 
	{
		errno = EINVAL;
		return -1;
	}

	memcpy(&req.gsr_group, grp, grplen);
	memcpy(&req.gsr_source, src, srclen);

	return (setsockopt(sockfd, family_to_level(grp->sa_family),MCAST_JOIN_SOURCE_GROUP, (char *)&req, sizeof(req)));
    #else
	switch (grp->sa_family) 
	{
        #ifdef IP_ADD_SOURCE_MEMBERSHIP
	case AF_INET: 
		{
			struct ip_mreq_source	mreq;
			struct ifreq			ifreq;

			memcpy(&mreq.imr_multiaddr,
				   &((struct sockaddr_in *) grp)->sin_addr,
				   sizeof(struct in_addr));
			memcpy(&mreq.imr_sourceaddr,
				   &((struct sockaddr_in *) src)->sin_addr,
				   sizeof(struct in_addr));

			if (ifindex > 0) 
			{
				if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) 
				{
					errno = ENXIO;	/* i/f index not found */
					return(-1);
				}
				goto doioctl;
			} 
			else if (ifname != NULL) 
			{
				strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
				doioctl:
				if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0)
				{
					return(-1);
				}
				memcpy(&mreq.imr_interface,&((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr,sizeof(struct in_addr));
			} 
			else
			{
				mreq.imr_interface.s_addr = htonl(INADDR_ANY);
			}

			return(setsockopt(sockfd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,&mreq, sizeof(mreq)));
		}
		#endif

        #ifdef	IPV6
	case AF_INET6: /* IPv6 source-specific API is MCAST_JOIN_SOURCE_GROUP */
        #endif
	default:
		errno = EAFNOSUPPORT;
		return(-1);
	}
    #endif
}

void Mcast_join_source_group(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen,const char *ifname, u_int ifindex)
{
	mcast_join_source_group(sockfd, src, srclen, grp, grplen,ifname, ifindex);
}

int mcast_block_source(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen)
{
    #ifdef MCAST_BLOCK_SOURCE
	struct group_source_req req;
	req.gsr_interface = 0;
	if (grplen > sizeof(req.gsr_group) || srclen > sizeof(req.gsr_source)) 
	{
		errno = EINVAL;
		return -1;
	}
	memcpy(&req.gsr_group, grp, grplen);
	memcpy(&req.gsr_source, src, srclen);
	return (setsockopt(sockfd, family_to_level(grp->sa_family),MCAST_BLOCK_SOURCE, (char *)&req, sizeof(req)));
    #else
	switch (grp->sa_family) 
	{
        #ifdef IP_BLOCK_SOURCE
	case AF_INET: 
		{
			struct ip_mreq_source	mreq;

			memcpy(&mreq.imr_multiaddr,&((struct sockaddr_in *) grp)->sin_addr,sizeof(struct in_addr));
			memcpy(&mreq.imr_sourceaddr,&((struct sockaddr_in *) src)->sin_addr,sizeof(struct in_addr));
			mreq.imr_interface.s_addr = htonl(INADDR_ANY);

			return(setsockopt(sockfd, IPPROTO_IP, IP_BLOCK_SOURCE,&mreq, sizeof(mreq)));
		}
        #endif

        #ifdef	IPV6
	case AF_INET6: /* IPv6 source-specific API is MCAST_BLOCK_SOURCE */
        #endif
	default:
		errno = EAFNOSUPPORT;
		return(-1);
	}
    #endif
}

void Mcast_block_source(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen)
{
	mcast_block_source(sockfd, src, srclen, grp, grplen);
}

int mcast_unblock_source(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen)
{
    #ifdef MCAST_UNBLOCK_SOURCE
	struct group_source_req req;
	req.gsr_interface = 0;
	if (grplen > sizeof(req.gsr_group) || srclen > sizeof(req.gsr_source)) 
	{
		errno = EINVAL;
		return -1;
	}
	memcpy(&req.gsr_group, grp, grplen);
	memcpy(&req.gsr_source, src, srclen);
	return (setsockopt(sockfd, family_to_level(grp->sa_family),MCAST_UNBLOCK_SOURCE, (char *)&req, sizeof(req)));
    #else
	switch (grp->sa_family) 
	{
        #ifdef IP_UNBLOCK_SOURCE
	case AF_INET: 
		{
			struct ip_mreq_source	mreq;

			memcpy(&mreq.imr_multiaddr,&((struct sockaddr_in *) grp)->sin_addr,sizeof(struct in_addr));
			memcpy(&mreq.imr_sourceaddr,&((struct sockaddr_in *) src)->sin_addr,sizeof(struct in_addr));
			mreq.imr_interface.s_addr = htonl(INADDR_ANY);

			return(setsockopt(sockfd, IPPROTO_IP, IP_UNBLOCK_SOURCE,
							  &mreq, sizeof(mreq)));
		}
	#endif

#ifdef	IPV6
	case AF_INET6: /* IPv6 source-specific API is MCAST_UNBLOCK_SOURCE */
#endif
	default:
		errno = EAFNOSUPPORT;
		return(-1);
	}
#endif
}

void Mcast_unblock_source(int sockfd, const struct sockaddr *src, socklen_t srclen,const struct sockaddr *grp, socklen_t grplen)
{
	mcast_unblock_source(sockfd, src, srclen, grp, grplen);
}

int mcast_set_loop(int fd, int onoff)
{
	u_char		flag;
	flag = onoff;
	return(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,(char *)&flag, sizeof(flag)));
}

int family_to_level(int family)
{
	switch (family) 
	{
	case AF_INET:
		return IPPROTO_IP;
        #ifdef	IPV6
	case AF_INET6:
		return IPPROTO_IPV6;
        #endif
	default:
		return -1;
	}
}

int sockfd_to_family(int sockfd)
{
	struct sockaddr_storage ss;
	socklen_t	len;

	len = sizeof(ss);
	if (getsockname(sockfd, (struct sockaddr *) &ss, &len) < 0)
	{
		return(-1);
	}
	return(ss.ss_family);
}

char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
    char		portstr[8];
    static char str[128];

	switch (sa->sa_family) 
	{
	case AF_INET: 
		{
			struct sockaddr_in	*sin = (struct sockaddr_in *) sa;

			if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
				return(NULL);
			if (ntohs(sin->sin_port) != 0) 
			{
				snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
				strcat(str, portstr);
			}
			return(str);
		}

        #ifdef	IPV6
	case AF_INET6: 
		{
			struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *) sa;

			str[0] = '[';
			if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL)
			{
				return(NULL);
			}
			if (ntohs(sin6->sin6_port) != 0) 
			{
				snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port));
				strcat(str, portstr);
				return(str);
			}
			return (str + 1);
		}
        #endif

        #ifdef	HAVE_SOCKADDR_DL_STRUCT
	case AF_LINK: 
		{
			struct sockaddr_dl	*sdl = (struct sockaddr_dl *) sa;

			if (sdl->sdl_nlen > 0)
			{
				snprintf(str, sizeof(str), "%*s (index %d)",sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);
			}
			else
			{
				snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);
			}
			return(str);
		}
        #endif
	default:
		snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",sa->sa_family, salen);
		return(str);
	}
    return (NULL);
}

